工控網(wǎng)首頁
>

應(yīng)用設(shè)計(jì)

>

機(jī)器人小強(qiáng)一號(hào)的制作過程

機(jī)器人小強(qiáng)一號(hào)的制作過程

2013/9/9 10:14:38

從對(duì)機(jī)器人感興趣開始,買了一堆書,也看了很多資料,決定先從最簡單的車輪機(jī)器人開始做。普通電腦雖然強(qiáng)大,但是不能直接采集外界環(huán)境的物理數(shù)據(jù),也不能直接控制電機(jī)。查找了下,雖然可以直接在電腦上接USB接口的數(shù)據(jù)采集器用于采集傳感器的數(shù)據(jù),也可以使用PCI的電機(jī)控制卡來驅(qū)動(dòng)各種電機(jī),不過成本有些高,暫時(shí)不考慮了。找了一圈,發(fā)現(xiàn)還是單片機(jī)方案廉價(jià),順便可以學(xué)習(xí)下單片機(jī)控制和作一些電路實(shí)驗(yàn)。于是最終決定實(shí)驗(yàn)方案采用單片機(jī)來做了。

零件
下面是采購的零件:
8位單片機(jī)Atmega168開發(fā)板。
電路面包板和連線用于驅(qū)動(dòng)車輪的兩個(gè)減速電機(jī)。沒有找到合適的齒輪,自己也沒有加工設(shè)備,圖簡單,所以直接用集成減速齒輪的電機(jī)代替了。

距離傳感器,作為機(jī)器人的主要傳感器,用來探測(cè)障礙物的距離。使用的是常用的紅外距離傳感器作為機(jī)器人的眼睛。

舵機(jī),用來控制機(jī)器人“眼睛”的方向。

下一步就可以驗(yàn)證簡單的功能了。

 

實(shí)驗(yàn)

 接下來先搞清楚怎么用單片機(jī)。
Hello world
 先讓單片機(jī)跑起來再說。習(xí)慣了操作系統(tǒng)下編程,第一次用單片機(jī)還真有些不習(xí)慣,擔(dān)心遇到問題,不過比較順利。這個(gè)程序用來點(diǎn)亮

單片機(jī)上的一個(gè)LED。

代碼:
int ledPin = 13; // LED connected to digital pin 13
<!--[if !supportEmptyParas]--> <!--[endif]-->
void setup()
{
 pinMode(ledPin, OUTPUT); // sets the digital pin as output
}
<!--[if !supportEmptyParas]--> <!--[endif]-->
void loop()
{
 digitalWrite(ledPin, HIGH); // sets the LED on
 delay(1000); // waits for a second
 digitalWrite(ledPin, LOW); // sets the LED off
 delay(1000); // waits for a second
}
<!--[if !supportEmptyParas]--> <!--[endif]-->
以間隔1000ms的時(shí)間把單片機(jī)的第13 個(gè)Pin腳循環(huán)輸出高低電平,從而達(dá)到點(diǎn)亮和熄滅LED功能。很簡單,就是驗(yàn)證下單片機(jī)是否可用。
控制舵機(jī)
舵機(jī)就是遙控模型上用來控制的,其實(shí)就是一個(gè)帶閉環(huán)控制的電機(jī),能轉(zhuǎn)動(dòng)到指定的角度。


工作原理是:控制信號(hào)由接收機(jī)的通道進(jìn)入信號(hào)調(diào)制芯片,獲得直流偏置電壓。它內(nèi)部有一個(gè)基準(zhǔn)電路,產(chǎn)生周期為20ms,寬度為1.5ms的基準(zhǔn)信號(hào),將獲 得的直流偏置電壓與電位器的電壓比較,獲得電壓差輸出。


最后,電壓差的正負(fù)輸出到電機(jī)驅(qū)動(dòng)芯片決定電機(jī)的正反轉(zhuǎn)。當(dāng)電機(jī)轉(zhuǎn)速一定時(shí),通過級(jí)聯(lián)減速齒輪帶動(dòng) 電位器旋轉(zhuǎn),使得電壓差為0,電機(jī)停止轉(zhuǎn)動(dòng)。
 在程序中控制舵機(jī)的轉(zhuǎn)動(dòng)角度,就是生成不同脈寬的PWM就行了。

上面的代碼簡單的生成一個(gè)PWM 驅(qū)動(dòng)舵機(jī)旋轉(zhuǎn),比較簡單。 代碼中用delay來實(shí)現(xiàn)延時(shí),如果是同時(shí)控制多個(gè)舵機(jī),用這樣的代碼是不行的,需要自己計(jì)算時(shí)間。因?yàn)橛胐elay整個(gè)單片機(jī)都“休息”了,無法執(zhí)行任何代碼。在實(shí)際實(shí)現(xiàn)中,還需要不斷的讀取傳感器輸入和進(jìn)行其他處理。

紅外距離傳感器
傳感器介紹:
SHARP紅外距離傳感器,用于模型或機(jī)器人制作,可以用來測(cè)量距離。每個(gè)模塊贈(zèng)送一根15cm長PH2.0的單頭排線.
<!--[if !supportEmptyParas]--> <!--[endif]-->
技術(shù)規(guī)格:
<!--[if !supportEmptyParas]--> <!--[endif]-->
探測(cè)距離:10-80cm
工作電壓:4-5.5V
標(biāo)準(zhǔn)電流消耗:33-50 mA
輸出量:模擬量輸出,輸出電壓和探測(cè)距離成比例

接好電源,把模擬信號(hào)輸出端接在單片機(jī)的模擬輸入Pin就行了。
 測(cè)試代碼:
int potPin = 2;
int ledPin = 13;
int val = 0;
<!--[if !supportEmptyParas]--> <!--[endif]-->
void setup() {
 pinMode(ledPin, OUTPUT);
}
<!--[if !supportEmptyParas]--> <!--[endif]-->
void loop() {
 val = analogRead(potPin); 
 digitalWrite(ledPin, HIGH); 
 delay(val); 
 digitalWrite(ledPin, LOW);
delay(val);
}
<!--[if !supportEmptyParas]--> <!--[endif]-->
運(yùn)行結(jié)果,led隨著傳感器距離的變化閃爍間隔也隨著變化。
控制電機(jī)
 常用的直流電機(jī)使用L293D來控制,使用H293的電路如下:

不過在驗(yàn)證是發(fā)現(xiàn),對(duì)于小電機(jī),直接用單片機(jī)的PWM端子來輸出不同電壓的來控制速度也是可行的,雖然不太精確,但是對(duì)于實(shí)現(xiàn)運(yùn)動(dòng)特征是足夠了。單片機(jī)無法輸出真正的線性模擬電壓,PWM是通過調(diào)整空占比間隔來模擬不同電壓值的。

測(cè)量了電機(jī)在空載和負(fù)載情況下電流都只有幾十毫安,所以先采取這種簡單的辦法驗(yàn)證。

直接把電機(jī)接到單片機(jī)的Gnd和 PWM Pin 9接口,然后在程序中直接向 Pin 9輸出就可以讓電機(jī)運(yùn)轉(zhuǎn)了。
int value = 0;  
int ledpin = 9;
<!--[if !supportEmptyParas]--> <!--[endif]-->
void setup()

 // nothing for setup
}
<!--[if !supportEmptyParas]--> <!--[endif]-->
void loop()

 for(value = 0 ; value <= 255; value+=5) 
 { 
 analogWrite(ledpin, value); 
 delay(30); 
 } 
 for(value = 255; value >=0; value-=5) 
 { 
 analogWrite(ledpin, value); 
 delay(30); 
 }
}
<!--[if !supportEmptyParas]--> <!--[endif]-->
上面的程序用不同的輸出值驅(qū)動(dòng)電機(jī),可以看到電機(jī)的旋轉(zhuǎn)效果。
<!--[if !supportEmptyParas]--> <!--[endif]-->
單片機(jī)和主要部件的驗(yàn)證基本就完成了,下一步要開始程序設(shè)計(jì)了。

軟件設(shè)計(jì)
思路    
在進(jìn)行代碼編寫之前,想找到一種簡介的實(shí)現(xiàn)低級(jí)智能機(jī)器人的方式。目前的工業(yè)機(jī)器人采用的是精確控制的方法,在程序中固化每種處理邏輯。用程序員的思維來完成對(duì)機(jī)器人的操作。
對(duì)于程序員來說,機(jī)器人無非就是外接了物理傳感輸入和運(yùn)動(dòng)控制輸出的一臺(tái)電腦,不管是64位多核CPU或者8位單片機(jī),只是性能的不同而已。理論上,都能通過程序設(shè)計(jì)來達(dá)到預(yù)定的目標(biāo)。如果按照計(jì)算機(jī)上的普通程序來設(shè)計(jì),那么大量的功能代碼會(huì)相互耦,每次為了增加一個(gè)新的運(yùn)動(dòng)功能或者任務(wù),都需要編制新的代碼,而新的代碼給原來的環(huán)路反饋系統(tǒng)帶來新的邏輯分支,所有的步驟都得經(jīng)過程序員的驗(yàn)證和設(shè)計(jì)。這樣的設(shè)計(jì)對(duì)于精確計(jì)算的PC程序或者擅長固定場(chǎng)景精確動(dòng)作的工業(yè)機(jī)器人來說,都沒有問題。但是對(duì)于這里要實(shí)現(xiàn)的“小強(qiáng)一號(hào)”機(jī)器人,是處在一個(gè)動(dòng)態(tài)的變化環(huán)境當(dāng)中,如果按照傳統(tǒng)的軟件設(shè)計(jì)邏輯,會(huì)存在大量耦合的邏輯分支,導(dǎo)致程序擴(kuò)展性很差。舉例來說,為了完成一個(gè)沿墻壁行走的功能,必須對(duì)各種傳感器輸入情況進(jìn)行判斷,然后做出預(yù)置的動(dòng)作序列。

如果要執(zhí)行的動(dòng)作和需要判斷的情況很多,那么程序邏輯分支就比較復(fù)雜,擴(kuò)展性也比較差,有沒有更好的適合機(jī)器人軟件設(shè)計(jì)的方法呢?
換一種思維來思考的話,我們要做的不是電腦程序,只是一個(gè)實(shí)驗(yàn)機(jī)器人。這個(gè)實(shí)驗(yàn)機(jī)器人能做到自然界昆蟲級(jí)的“智能”就很不錯(cuò)了。 試想,一只螞蟻,一只蟑螂會(huì)去思考這么復(fù)雜的邏輯分支嗎?去考慮各種情況下應(yīng)該采取的動(dòng)作? 不太可能。我們用了復(fù)雜的想法去解決簡單的事情。
機(jī)器人和計(jì)算機(jī)的主要區(qū)別在于,計(jì)算機(jī)是按照預(yù)先規(guī)劃的指令運(yùn)行,而機(jī)器人需要根據(jù)變化的環(huán)境選擇合適動(dòng)作。我們首先可以簡化動(dòng)作模型,我把機(jī)器人的執(zhí)行任務(wù)分成3個(gè)層次:任務(wù)-》行為-》動(dòng)作任務(wù)——機(jī)器人完成的一個(gè)期望目標(biāo),比如“在一個(gè)范圍內(nèi)收集地面上的垃圾”可以界定為一個(gè)機(jī)器人的任務(wù)。
行為——行為是對(duì)任務(wù)的分解,行為是機(jī)器人根據(jù)環(huán)境變化選擇要做什么。比如碰到墻壁需要進(jìn)行躲避。電源不足需要充電,就可以劃分為一個(gè)行為。
動(dòng)作——機(jī)器人最終控制電機(jī)等輸出設(shè)備做出的動(dòng)作,比如前進(jìn),后退,轉(zhuǎn)彎。轉(zhuǎn)動(dòng)攝像頭都可以劃分成一個(gè)動(dòng)作單元。
說明:任務(wù)由一系列的行為構(gòu)成;行為有一個(gè)或者多個(gè)動(dòng)作組成,動(dòng)作是立即執(zhí)行的最小單元。在任意一個(gè)時(shí)刻,只有一個(gè)動(dòng)作可以得到執(zhí)行。
軟件實(shí)現(xiàn)的對(duì)象就是分解出簡單的行為,針對(duì)每個(gè)行為單獨(dú)實(shí)現(xiàn),互相之間無干涉、無耦合。當(dāng)多個(gè)行為要輸出互相矛盾的動(dòng)作時(shí),通過一個(gè)行為優(yōu)先級(jí)表來決定優(yōu)先級(jí)高的行為來做出動(dòng)作。在這個(gè)思路中,參考了基于行為編程的理論,關(guān)于詳細(xì)的基于行為編程的描述,可以在網(wǎng)上搜索“Behavior-based robotics”。
    通過這種設(shè)計(jì)思路,可以實(shí)現(xiàn)對(duì)動(dòng)物反射特性的模擬,不需要把精力放在復(fù)雜的邏輯處理上,只需要根據(jù)分解出的基本行為實(shí)現(xiàn)一個(gè)一個(gè)小的行為單元。每個(gè)行為單元只關(guān)心自己的傳感輸入和需要輸出的控制動(dòng)作就行了。確定了設(shè)計(jì)思路,下一部分開始針對(duì)小強(qiáng)一號(hào)來設(shè)計(jì)軟件了。

參考資料,有興趣的可以閱讀:
http://www-robotics.usc.edu/~maja/publications/mitcs.ps.gz   (這篇文章描述了如何分解行為,需要安裝 GSView)
http://www.research.ibm.com/people/j/jhc/pubs/jhc-design.pdf
http://www-robotics.usc.edu/~maja/bbs.html
《基于行為的機(jī)器人實(shí)戰(zhàn)指南》 中譯版

強(qiáng)一號(hào)結(jié)構(gòu)非常簡單,傳感器只采用了個(gè)紅外距離傳感器作為機(jī)器人的“眼睛”,使用兩個(gè)電機(jī)進(jìn)行運(yùn)動(dòng),距離傳感器連接在一個(gè)舵機(jī)上,作為“頭部”可以左右范圍的轉(zhuǎn)動(dòng)。機(jī)器人的行為最簡單的就是巡航行為,巡航行為就是給電機(jī)電流,電機(jī)轉(zhuǎn)動(dòng)而已。那么發(fā)生碰撞怎么辦?在巡航行為中,不用考慮碰撞,否則又會(huì)變成復(fù)雜的判斷邏輯。為了避免碰撞,設(shè)計(jì)一個(gè)獨(dú)立的避免碰撞的“逃離”行為。逃離行為從距離傳感器獲取障礙物距離信息,簡單的判斷前方是否有障礙,進(jìn)行避讓。由于多個(gè)行為都可能控制電機(jī),所以需要一個(gè)仲裁器根據(jù)優(yōu)先級(jí)來判斷到底執(zhí)行那個(gè)邏輯部分輸出的控制指令。

下面用圖來說明這種情況:

如果需要增加其他更加復(fù)雜的智能,那么只需要增加對(duì)應(yīng)的行為單元就行了,不用修改已有的邏輯結(jié)構(gòu)。每個(gè)行為單元只需要處理自己關(guān)心的傳感器和需要控制的動(dòng)作執(zhí)行部分。這種方式的好處就是程序邏輯變得非常簡單,功能單元之間不會(huì)存在互相影響的弊端。      

下面的代碼是“巡航”行為:

class BhCruis:public Behavior

{

public:

      

publicSPAN style="mso-tab-count: 2">           

    BhCruis(const char* name):Behavior(name){

       };

       BhCruis();

       void Run();

       void Setup();

};

void BhCruis::Setup(){

}

void BhCruis::Run(){

    int bid = GetId();

    GO_speed_left[bid] = 255;

    GO_speed_right[bid] = 255;

    GT_beh_action[ACTION_TYPE_MOTOR][bid] = true;

}

上面的代碼很簡單,就是讓兩個(gè)電機(jī)以同樣的速度暈裝,其他都不用考慮。對(duì)于某些行為,需要引入稍微復(fù)雜一些的處理,比如發(fā)現(xiàn)障礙物,首先要停下來,然后判斷是應(yīng)該往左還是往右,做出決定之后,再進(jìn)行具體的動(dòng)作。針對(duì)這種不能在一個(gè)時(shí)刻完成,要經(jīng)過幾個(gè)不同的狀態(tài)才能處理完成的行為,可以用狀態(tài)機(jī)來解決。下圖是“逃離”行為的狀態(tài)機(jī):


對(duì)于行為實(shí)現(xiàn)自己的狀態(tài)機(jī),在行為實(shí)現(xiàn)的代碼內(nèi)部實(shí)現(xiàn),而不影響其他行為。這種結(jié)構(gòu)可以讓每個(gè)行為子關(guān)心自己的實(shí)現(xiàn)方式,從而最大的降低軟件復(fù)雜度,方便功能添加和修改。逃離行為狀態(tài)機(jī)實(shí)現(xiàn)原型代碼:  void 

void BhEscape::Run(){

    int bid = GetId();

    // 狀態(tài)機(jī)實(shí)現(xiàn)

    switch(state){

        case 0: // 前方距離過小

            if(GI_distance[DISTANCE_FORWORD] < 30){

                GO_speed_left[bid] = 0;

                GO_speed_right[bid] = 0;

                GT_beh_action[ACTION_TYPE_MOTOR][bid] = true;

                timestart = millis();

                state++;   // 狀態(tài)變化

            }else{

                GT_beh_action[ACTION_TYPE_MOTOR][bid] = false;

            }

          

            break;

        case 1SPAN style="mso-spacerun: yes">  // 觀察左右距離

            if(millis() - timestart > 1000){

                GO_eyeAngle[bid] = 0;

                GT_beh_action[ACTION_TYPE_HEAD][bid] = true;

                timestart = millis();

                state++;

            }

        case 2SPAN style="mso-spacerun: yes">  // 觀察左右距離

            if(millis() - timestart > 1000){

                GO_eyeAngle[bid] = 180;

                GT_beh_action[ACTION_TYPE_HEAD][bid] = true;

                timestart = millis();

                state++;

            }

        case 3SPAN style="mso-spacerun: yes">  // 決定往哪邊轉(zhuǎn)彎

            if(millis() - timestart > 1000){            

                GO_eyeAngle[bid] = Angle_Center_90;

                GT_beh_action[ACTION_TYPE_HEAD][bid] = true;

               

                if(GI_distance[DISTANCE_LEFT_1] > GI_distance[DISTANCE_RIGHT_1]){

                    // 左轉(zhuǎn)

                    GO_speed_left[bid] = 0;

                    GO_speed_right[bid] = 255;

                }else{

                    //右轉(zhuǎn)

                    GO_speed_left[bid] = 255;

                    GO_speed_right[bid] = 0;

                }

                GT_beh_action[ACTION_TYPE_MOTOR][bid] = true;

                state = 0;

                Delay(2000);

            }

          

        default:

            break;

    }

}

    這種基于行為單元的實(shí)現(xiàn)方法比較類似生物的反射行為,完整的代碼在下載專區(qū)進(jìn)行下載。完成了基本的代碼,下一部分需要構(gòu)建機(jī)器人的機(jī)構(gòu)和測(cè)試了。

結(jié)構(gòu)和測(cè)試 實(shí)驗(yàn)機(jī)器人的結(jié)構(gòu)就地取材,用了一個(gè)拼裝玩具小車的零件,如下圖:
為了安裝電機(jī)和傳感器,重新拼裝了下,變成這個(gè)樣子:
有了基本的結(jié)構(gòu),可以測(cè)試功能了,驗(yàn)證功能是否正常。
功能測(cè)試完成,放到地上實(shí)際跑一下:
有點(diǎn)好玩,基本達(dá)到可以巡航和壁障的功能,不過功能太過于簡單,只能相當(dāng)于一個(gè)玩具。

投訴建議

提交

查看更多評(píng)論
其他資訊

查看更多

自動(dòng)化機(jī)床的故障排除技術(shù)淺析

安川焊接機(jī)器人編程

ABB機(jī)器人控制軟件RobotWare應(yīng)用手冊(cè)SafeMove(英文)

ABB IRB7600 機(jī)器人維護(hù)信息

ABB IRC5P機(jī)器人培訓(xùn)教材